# include "array-list.h"

ArrayList * newArrayList (int init) {
	ArrayList *new = (ArrayList *) malloc(sizeof(ArrayList));
	if (!new) logMessage("util.lists","array-list.c","newArrayList","Memória insuficiente (A)",CRITICAL);
	new->size = init;
	new->elems = 0;
	new->list = (void **) malloc(sizeof(void *)*init);
	if (!new->list) logMessage("util.lists","array-list.c","newArrayList","Memória insuficiente (B)",CRITICAL);
	return new;
}

void freeArrayList (ArrayList *lst) {
	if (lst && lst->list) free(lst->list);
	if (lst) free(lst);
}

int arrayGetLength (ArrayList *lst) {
	if (!lst) return 0;
	return lst->elems;
}

void * arrayGet (ArrayList *list, int indice) {
	if (indice >= list->elems || indice < 0) return NULL;
	else return list->list[indice];
}

static int needsAdd (ArrayList *list) {
	if (list->size > list->elems + 1) return 0;
	else return 1;
}
static int listAlloc (ArrayList *list) {
	void **aux = list->list;
	list->list = (void **) malloc(sizeof(void *)*(list->size+LIST_ALLOC_JUMP));
	if (!list->list) logMessage("util.lists","array-list.c","listAlloc","Memoria insuficiente",CRITICAL);
	int i;
	list->size += LIST_ALLOC_JUMP;
	for (i=0;i<list->elems;i++) list->list[i] = aux[i];
	free(aux);
}
static int listSwift (ArrayList *list, int indice) {
	if (needsAdd(list)) listAlloc(list);
	int i;
	for (i=list->elems;i>indice;i--) {
		list->list[i] = list->list[i-1];
	}
}
int arrayInsert (ArrayList *list, void *data) {
	if (needsAdd(list)) listAlloc(list);
	list->list[list->elems++] = data;
	return 1;
}
int arrayInsertAt (ArrayList *list, int ind, void *d, int r) {
	if (ind>list->elems || ind < 0) return 0;
	else {
		if (r) list->list[ind] = d;
		else {
			listSwift(list,ind);
			list->elems++;
			list->list[ind] = d;
		}
	}
	return 1;
}
int arraySwap (ArrayList *list, int indA, int indB) {
	void *aux;
	if (indA < 0 || indA > list->elems) return 0;
	else if (indB < 0 || indB > list->elems) return 0;
	else {
		aux = list->list[indA];
		list->list[indA] = list->list[indB];
		list->list[indB] = aux;
	}
	return 1;
}

int arrayRemoveFrom (ArrayList *lst, int ind) {
	int i;
	if (ind < 0 || ind > lst->elems-1) return 0;
	else {
		for (i=ind;i<(lst->elems-1);i++) 
			lst->list[i] = lst->list[i+1];
		lst->elems--;
	}
	return 1;
}

int arrayRemove (ArrayList *lst, void *data, equalFunction func) {
	int i;
	for (i=0;i<lst->elems;i++) 
		if ((func)(data,lst->list[i]))
			return arrayRemoveFrom(lst,i);
	return 0;
}

int arrayIndexOf (ArrayList *lst, void *data, equalFunction func) {
	int i;
        for (i=0;i<lst->elems;i++)
                if ((func)(data,lst->list[i]))
                        return i;
        return -1;
}

void arraySort (ArrayList *lst, equalFunction func, int desc) {
        int i,j,a;
	if (!desc) {
		for (i=1;i<lst->elems;i++) {
                	j=i-1;
                	while (j>=0 && (func)(lst->list[j],lst->list[i]) == 1) {
                	        arraySwap(lst,i,j);
                	        j--;
                	}
        	}
	} else {
        	for (i=lst->elems-2;i>=0;i--) {
			j=i+1; a = 0;
			while (j<lst->elems && (func)(lst->list[i+a],lst->list[j]) == -1) {
				arraySwap(lst,i+a,j);
				j++; a++;
			}
		}
	}
}
